Exporting ALV to Memory2

Wir greifen den Trick – nach SUBMIT an die ALV-Daten im Office-Format zu gelangen – noch einmal auf und zeigen, wie man aus dem XML-String eine Tabelle erhält.

In diesem Beispiel rufen wir das Beispielprogramm BCALV_FULLSCREEN_DEMO auf, um mittels ALV-Grid Daten zu erzeugen.

Die Flugdatenbank muss natürlich gefüllt sein!!

BCALV_FULLSCREEN_DEMO

Die grundlegenden Bestandteile sind bereits im vorherigen Artikel erläutert worden. In diesem Programm zeigen wir, wie man die im XML-Format vorliegenden Daten in eine interne Tabelle umwandelt.

Das XML-Ergebnis wird dabei Ereignisgesteuert bearbeitet. Das bedeutet: Die XML-Tags werden Stück für Stück durchlaufen und im Programm wird entsprechend darauf reagiert.

XML

Die zurückgelieferte XML-Struktur, die die Tabelle beschreibt ist recht komplex. Hier ist die Beispiel-XML-Datei zu sehen: http://pastebin.com/XkgctkJA

Uns interessieren jedoch nur die folgenden Tags:

Anzahl der Spalten

<Table><Column/><Column/></Table>

Zellen und Zelleninhalte

<Cell><Data>Inhalt</data></cell>

Coding

REPORT  zz_export_alv_to_memory_demo01.

*----------------------------------------------------------------------*
*       CLASS lcl_xml DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_xml DEFINITION.

  PUBLIC SECTION.
CLASS-METHODS call_report  IMPORTING iv_repid TYPE syrepid
iv_list  TYPE char1.

    CLASS-METHODS create_table IMPORTING iv_fields TYPE i
EXPORTING ed_table TYPE REF TO data.

    CLASS-METHODS display_data IMPORTING it_table TYPE STANDARD TABLE PREFERRED PARAMETER it_table.

ENDCLASS.                    "lcl_xml DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_xml IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_xml IMPLEMENTATION.

  METHOD call_report.

*== Data
DATA lv_guid   TYPE guid_32.
DATA ls_params TYPE rsparams.
DATA lt_params TYPE TABLE OF rsparams.

*== Create and export GUIID for ALV
lv_guid = cl_salv_export_db_storage=>create_guid( ).
EXPORT l_mode = 'M' TO MEMORY ID 'ALV_EXTRACT_MODE'.
EXPORT l_guid = lv_guid TO MEMORY ID 'ALV_EXTRACT_GUID'.

*== Call Report
    SUBMIT (iv_repid)
WITH SELECTION-TABLE lt_params
AND RETURN.                                       "#EC CI_SUBMIT

    DATA lv_xstring           TYPE xstring.
DATA lr_stream_factory    TYPE REF TO if_ixml_stream_factory.
DATA lr_ixml              TYPE REF TO if_ixml.
DATA lr_istream           TYPE REF TO if_ixml_istream.
DATA lr_doc               TYPE REF TO if_ixml_document.
DATA lr_parser            TYPE REF TO if_ixml_parser.
DATA lv_events            TYPE i.
DATA lv_number_of_fields  TYPE i.

    DATA lr_event             TYPE REF TO if_ixml_event.
DATA lv_type              TYPE i.
DATA lv_current_node      TYPE string.
DATA lv_current_value     TYPE string.
DATA lv_cell_index        TYPE i.

*== Import XML-data from AVL and convert to stream
lv_xstring        = cl_salv_export_db_storage=>import_xmlstring
( guid  = lv_guid ).
lr_ixml           = cl_ixml=>create( ).
lr_stream_factory = lr_ixml->create_stream_factory( ).
lr_istream        = lr_stream_factory->create_istream_xstring
( string = lv_xstring ).

    lr_doc            = lr_ixml->create_document( ).

*== Create parser for document
    lr_parser   = lr_ixml->create_parser(
document       = lr_doc
istream        = lr_istream
stream_factory = lr_stream_factory ).

*== deactivate DOM generation
lr_parser->set_dom_generating( space ).

*== data for dynamically generated internal table
DATA ld_table            TYPE REF TO data.
FIELD-SYMBOLS <table>    TYPE STANDARD TABLE.
FIELD-SYMBOLS <row>      TYPE ANY. "line of <table>.
FIELD-SYMBOLS <cell>     TYPE string.

*== define Parser events
lv_events = if_ixml_event=>co_event_element_pre2
+ if_ixml_event=>co_event_element_post
+ if_ixml_event=>co_event_text_post.

*== Register XML-Events
lr_parser->set_event_subscription( lv_events ).

    DO.

*== get next event (XML-tag)
lr_event = lr_parser->parse_event( ).
IF lr_event IS INITIAL.
EXIT.
ENDIF.

*== get type of event
lv_type = lr_event->get_type( ).
*== New element
CASE lv_type.
WHEN if_ixml_event=>co_event_element_pre2.
*===> Event "PRE2"
lv_current_node = lr_event->get_name( ).
IF iv_list <> space.
WRITE: / lv_current_node.
ENDIF.

          CASE lv_current_node.
WHEN 'Column'.
*=====> New Column: Add column counter
ADD 1 TO lv_number_of_fields.

            WHEN 'Row'.
*=====> New Row
IF <table> IS NOT ASSIGNED.
*=====> Create table if not done yet
create_table( EXPORTING iv_fields = lv_number_of_fields
IMPORTING ed_table  = ld_table ).

                ASSIGN ld_table->* TO <table>.
ENDIF.

*=====> Insert new table line
APPEND INITIAL LINE TO <table> ASSIGNING <row>.
CLEAR lv_cell_index.

            WHEN 'Cell'.
*======> new cell data:
ADD 1 TO lv_cell_index.
ASSIGN COMPONENT lv_cell_index
OF STRUCTURE <row> TO <cell>.
ENDCASE.

        WHEN if_ixml_event=>co_event_text_post.
*===> Event "TEXT"
CASE lv_current_node.
WHEN 'Data'.
*=====> get cell value and assign to table cell
<cell> = lr_event->get_value( ).
ENDCASE.

          IF iv_list <> space.
lv_current_value = lr_event->get_value( )..
WRITE lv_current_value COLOR COL_TOTAL.
ENDIF.

        WHEN if_ixml_event=>co_event_element_post.
*===> Event "POST"
IF iv_list <> space.
lv_current_node = lr_event->get_name( ).
WRITE: lv_current_node COLOR COL_GROUP.
ENDIF.

      ENDCASE.
ENDDO.

*== Display table
    IF <table> IS ASSIGNED.
display_data( <table> ).
ENDIF.

  ENDMETHOD.                    "call_report

METHOD create_table.

*== field catalog
    DATA lt_fcat             TYPE lvc_t_fcat.
FIELD-SYMBOLS <fcat>     TYPE lvc_s_fcat.

*== create field catalog for internal table
    DO iv_fields TIMES.
*== cell
APPEND INITIAL LINE TO lt_fcat ASSIGNING <fcat>.
<fcat>-fieldname = sy-index.
CONDENSE <fcat>-fieldname.
<fcat>-tabname   = 'GT_TABLE'.
<fcat>-inttype   = 'g'. "String
ENDDO.

*== generate internal table from given field catalog
CALL METHOD cl_alv_table_create=>create_dynamic_table
EXPORTING
it_fieldcatalog           = lt_fcat
IMPORTING
ep_table                  = ed_table
EXCEPTIONS
generate_subpool_dir_full = 1
OTHERS                    = 2.

  ENDMETHOD.                    "create_table

  METHOD display_data.

*== Data
DATA lv_col          TYPE i.
FIELD-SYMBOLS <row>  TYPE ANY.
FIELD-SYMBOLS <cell> TYPE string.

*== Display all table lines
LOOP AT it_table ASSIGNING <row>.
NEW-LINE.
DO.
*== Display each table cell
ASSIGN COMPONENT sy-index OF STRUCTURE <row> TO <cell>.
IF sy-subrc = 0.
lv_col = ( sy-index - 1 ) * 21.
WRITE AT lv_col(19)  <cell> COLOR COL_POSITIVE.
ELSE.
EXIT. "from do
ENDIF.
ENDDO.
ENDLOOP.
ENDMETHOD.                    "display_data

ENDCLASS.                    "lcl_xml IMPLEMENTATION

***___________________________________________________________________
***
*** SELECTION SCREEN
***___________________________________________________________________
***

SELECTION-SCREEN BEGIN OF BLOCK reps   WITH FRAME TITLE text-var.
PARAMETERS p_repid TYPE syrepid        DEFAULT 'BCALV_FULLSCREEN_DEMO'.
PARAMETERS p_data  RADIOBUTTON GROUP x DEFAULT 'X'.
PARAMETERS p_list  RADIOBUTTON GROUP x.
SELECTION-SCREEN END OF BLOCK reps.

START-OF-SELECTION.

*== Start report
lcl_xml=>call_report( EXPORTING iv_repid = p_repid
iv_list  = p_list ).

 

Enno Wulff

COMMENTS

  • <cite class="fn">maurerwe</cite>

    Eine schöne Lösung – aber:
    Die Ergebnistabelle ist sehr ‘neutral’: Alle Spalten sind vom Typ String.
    Insbesondere ist eine Datumsspalte im Format yyyy-mm-tt, was eine Weiterverarbeitung
    zumindest erschwert.
    Schöner wäre eine Tabelle, die technisch genau so aufgebaut ist wie im
    Layout der ALV-Ausgabe des Reports.
    Ich habe mal versucht mit dem FB LT_DBDATA_READ_FROM_LTDX dem ALV-Report sein Layout zu entlocken.
    Dadurch bekommt man leider auch nur die Feldnamen mit diversen Parametern und eben nicht die Datenelemente.
    Gibt es für EXPORT l_mode = ‘M’ TO MEMORY ID ‘ALV_EXTRACT_MODE’ vielleicht noch andere Ausprägungen,
    die dafür sorgen, dass mehr technische Information in die XML-Daten gelangt?
    Statt ‘M’ habe ich im System auch ‘B’, ‘E’ und ‘F’ gesehen.
    Viele Grüße
    Werner Maurer

    • <cite class="fn">Enno Wulff</cite>

      Hui. Das ist aber schon lange her… 😉
      Evtl. kommst du mit der Methode CL_SALV_EXPORT_DB_STORAGE=>IMPORT_ALV_VARIANT nach Aufruf des Reports weiter.
      Für FB LT_VARIANT_LOAD braucht man aber ausser dem Reportnamen und des Layouts (DISVARIANT) auch einen Tabellennamen, wenn ich das richtig sehe. Genau der fehlt aber.
      Zudem ist ja auch nicht sicher, dass der ALV überhaupt ein gespeichertes Layout benutzt hat.

      Ob es noch weitere Parameter gibt, weiß ich nicht.

      • <cite class="fn">maurerwe</cite>

        Vielen Dank für die prompte Reaktion.
        Die Methode CL_SALV_EXPORT_DB_STORAGE=>IMPORT_ALV_VARIANT hilft mir schon ein bisschen weiter – mit ihr kann ich prüfen, ob ein gespeichertes Layout benutzt wurde.
        Dann kann ich mit dem FB LT_DBDATA_READ_FROM_LTDX die Details zum Layout ermitteln. Leider eben nur die Feldnamen etc. Mit den Feldnamen und der Struktur, die dem ALV zugrunde liegt, kann ich dann weiterkämpfen.

Leave a Comment